package com.example.qt.ptplatform.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.qt.ptplatform.entity.Promotions;
import com.example.qt.ptplatform.entity.Torrent;
import com.example.qt.ptplatform.entity.User;
import com.example.qt.ptplatform.mapper.PromotionsMapper;
import com.example.qt.ptplatform.mapper.TorrentMapper;
import com.example.qt.ptplatform.mapper.UserMapper;
import com.example.qt.ptplatform.service.PromotionsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class PromotionsServiceImpl implements PromotionsService {

    @Autowired
    private PromotionsMapper promotionsMapper;

    @Autowired
    private UserMapper userMapper;  // 用于更新用户表

    @Autowired
    private TorrentMapper torrentMapper;  // 用于更新资源表

    /**
     * 创建促销活动
     */
    @Override
    public long createPromotion(Promotions promotions) {
        try {
            // 打印收到的 promotions 对象
            System.out.println("Received promotion: " + promotions);
            // 检查 Promotions 对象本身是否为 null
            if (promotions == null) {
                throw new IllegalArgumentException("促销活动对象不能为空");
            }

            // 校验活动名称不能为空
            if (promotions.getName() == null || promotions.getName().isEmpty()) {
                throw new IllegalArgumentException("活动名称不能为空");
            }

            // 校验活动时间是否合法
            if (promotions.getPStartTime() == null || promotions.getPEndTime() == null) {
                throw new IllegalArgumentException("活动时间不能为空");
            }
            if (promotions.getPStartTime().isAfter(promotions.getPEndTime())) {
                throw new IllegalArgumentException("活动时间设置不正确，请重新设定。");
            }

            // 校验上传量系数和下载量系数是否合法（系数应大于等于 0）
            if (promotions.getUploadCoeff() == null || promotions.getUploadCoeff() < 0) {
                throw new IllegalArgumentException("上传量系数必须为非负数");
            }
            if (promotions.getDownloadCoeff() == null || promotions.getDownloadCoeff() < 0) {
                throw new IllegalArgumentException("下载量系数必须为非负数");
            }

            // 校验时间范围是否合理
            if (promotions.getTimeRange() == null) {
                throw new IllegalArgumentException("时间范围不能为空");
            }

            // 校验参与条件是否有效（应该为1到5之间的整数）
            if (promotions.getCriteria() == null || promotions.getCriteria() < 1 || promotions.getCriteria() > 5) {
                throw new IllegalArgumentException("参与条件错误，请设置为1-5的整数");
            }

            // 保存促销活动到数据库
            promotionsMapper.insert(promotions);  // promoId 会由数据库自增

            // 清空所有用户和资源的 `is_promo` 字段（置为 0）
            resetPromoStatus();

            // 更新用户表中的 `is_promo` 属性（根据等级判断）
            updateUserPromoStatus(promotions);

            // 更新资源表中的 `is_promo` 属性（根据时间和其他条件判断）
            updateResourcePromoStatus(promotions);

            // 返回活动ID
            return promotions.getPromoId();  // 数据库会自动设置 promoId
        }
        catch (Exception e) {
            // 记录异常信息
            e.printStackTrace();  // 打印堆栈跟踪信息
            throw new RuntimeException("错误信息：" + e.getMessage(), e);
        }
    }

    // 清空所有用户和资源的 `is_promo` 字段（置为 0）
    private void resetPromoStatus() {
        // 更新所有用户表中的 `is_promo` 为 0
        userMapper.resetUserPromoStatus();

        // 更新所有资源表中的 `is_promo` 为 0
        torrentMapper.resetTorrentPromoStatus();
    }

    // 更新用户表中的 `is_promo` 属性（根据等级判断）
    private void updateUserPromoStatus(Promotions promotions) {
        // 根据用户等级 `criteria` 更新符合条件的用户的 `is_promo` 字段
        userMapper.updatePromoStatusForEligibleUsers(promotions.getCriteria());
    }

    // 更新资源表中的 `is_promo` 属性（根据时间和其他条件判断）
    private void updateResourcePromoStatus(Promotions promotions) {
        // 获取活动开始时间、结束时间和时间范围
        LocalDateTime startTime = promotions.getPStartTime();
        LocalDateTime endTime = promotions.getPEndTime();
        int timeRange = promotions.getTimeRange();
        // 打印参数
        System.out.println("startTime: " + startTime);
        System.out.println("endTime: " + endTime);
        System.out.println("timeRange: " + timeRange);
        // 调用方法更新符合条件的资源的 is_promo 字段
        torrentMapper.updatePromoStatusForEligibleTorrents(startTime, endTime, timeRange);
    }

    @Override
    public Promotions getPromotionDetails(long promoId) {
        //查询数据库中指定促销活动号的详细信息
        return promotionsMapper.selectById(promoId);
    }

    @Override
    public List<Promotions> getPromotionList(int page, int perPage) {
        // 使用 MyBatis-Plus 分页插件进行分页查询
        Page<Promotions> pageObj = new Page<>(page, perPage);
        // 执行分页查询
        return promotionsMapper.selectPage(pageObj, null).getRecords();
    }

    @Override
    public long getPromotionCount() {
        // 获取促销活动总条数
        return promotionsMapper.selectCount(null);
    }

    @Override
    public boolean deletePromotion(long promoId) {
        int deleteRows = promotionsMapper.deleteById(promoId);
        return deleteRows > 0;
    }

    /**
     * 获取最优促销力度-下载量
     */
    @Override
    public List<Promotions> getBestDownloadPromo(Long userId, Long torrentId) {
        User user = userMapper.selectById(userId);
        if(user == null) {
            throw new IllegalArgumentException("用户不存在");
        }

        Torrent torrent = torrentMapper.selectById(torrentId);
        if(torrentId == null) {
            throw new IllegalArgumentException("资源不存在");
        }

        //获取当前时间有效的所有促销活动
        LocalDateTime currentTime = LocalDateTime.now();
        List<Promotions> activePromos = promotionsMapper.getActivePromos(currentTime);

        //筛选符合条件的促销活动
        List<Promotions> eligiblePromos = new ArrayList<>();
        for (Promotions promo : activePromos) {
            // 判断资源是否符合促销条件
            boolean resourceEligibleForPromo = torrent.getUploadTime() != null &&
                    // 判断上传时间是否在促销活动开始前 timeRange 天内
                    (Duration.between(torrent.getUploadTime(), promo.getPStartTime()).toDays() <= promo.getTimeRange());
            // 判断用户是否符合促销条件
            boolean userEligibleForPromo = user.getLevel() >= promo.getCriteria();

            // 打印筛选的资源和用户是否符合促销条件
            System.out.println("检查资源 " + torrentId + " 和用户 " + userId + " 是否符合促销活动 " + promo.getPromoId() + " 的条件");
            System.out.println("资源符合条件: " + resourceEligibleForPromo);
            System.out.println("用户符合条件: " + userEligibleForPromo);

            if (resourceEligibleForPromo && userEligibleForPromo) {
                eligiblePromos.add(promo);
            }
        }

        // 打印符合条件的促销活动
        System.out.println("符合条件的促销活动：");
        eligiblePromos.forEach(promo -> System.out.println("促销活动 ID: " + promo.getPromoId() + ", 名称: " + promo.getName()));

        //返回下载量系数最小的促销活动
        if (eligiblePromos.isEmpty()) {
            return new ArrayList<>();
        }
        //以下载量系数进行排序，获取最小的促销活动
        Optional<Promotions> bestPromotion = eligiblePromos.stream()
                .min(Comparator.comparing(Promotions::getDownloadCoeff)); // 获取最小下载量系数的促销活动

        // 如果存在最小促销活动，返回列表，否则返回空列表
        return bestPromotion.map(Collections::singletonList).orElseGet(Collections::emptyList);
    }

    /**
     * 获取最优促销力度-上传量
     */
    @Override
    public Promotions getBestUploadPromo(Long userId) {
        //获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new IllegalArgumentException("用户不存在");
        }

        //获取当前时间有效的所有促销活动
        LocalDateTime currentTime = LocalDateTime.now();
        List<Promotions> activePromos = promotionsMapper.getActivePromos(currentTime);

        //筛选符合条件的促销活动
        List<Promotions> eligiblePromos = new ArrayList<>();
        for (Promotions promo : activePromos) {
            // 判断用户是否符合促销条件
            boolean userEligibleForPromo = user.getLevel() >= promo.getCriteria();

            if (userEligibleForPromo) {
                eligiblePromos.add(promo);
            }
        }

        // 4. 返回上传量系数最大的促销活动
        if (eligiblePromos.isEmpty()) {
            return null;
        }

        // 以上传量系数排序，取最大的
        return eligiblePromos.stream().max(Comparator.comparing(Promotions::getUploadCoeff)).orElse(null);
    }

}
